<?php
namespace app\api\logic;

use app\api\exception\BaseException;
use Flc\Dysms\Client;
use Flc\Dysms\Request\SendSms;
use PHPMailer;
use think\Cache;

class ValidateCode
{

    //默认验证码
    const DEFAULT_CODE='123123';

    public $max_life=300;  //验证码有效时间
    public $next_send_time=60;  //下次发送时间

    protected $name;
    protected $scene;
    protected $key='_validate_code_';

    protected $code='';
    protected $life=0;
    protected $next_time=0;


    protected $mail_template=[
        'default'=>[
            'subject'=>'验证邮箱',
            'content'=>'<p>您正在进行邮箱验证，验证码是：%s</p> <p>如果这不是你的邮件请忽略，很抱歉打扰你，请原谅。</p>'
        ],
        'bind'=>[
            'subject'=>'绑定邮箱',
            'content'=>'<p>您正在进行邮箱绑定操作，验证码是：%s，此验证码5分钟内有效。</p> <p>如果这不是你的邮件请忽略，很抱歉打扰你，请原谅。</p>'
        ],
        'forgot'=>[
            'subject'=>'找回密码',
            'content'=>'<p>您正在进行通过邮箱找回密码操作，验证码是：%s，请勿泄露给其他人。</p> <p>如果这不是你的邮件请忽略，很抱歉打扰你，请原谅。</p>'
        ],

    ];
    function __construct($name,$scene='default')
    {
        $this->name=$name;
        $this->scene=$scene;
        $this->key=md5($name.$this->key.$scene);
        $data=Cache::get($this->key);
        if($data){
            $this->code=isset($data['code'])?$data['code']:'';
            $this->life=isset($data['life'])?$data['life']:'';
            $this->next_time=isset($data['next_time'])?$data['next_time']:'';
        }


    }

    /**
     * 存储到缓存
     */
    function save($init=false){
        if($init){
            $data=[
                'code'=>'',
                'life'=>0,
                'next_time'=>0
            ];
        }else{
            $now=time();
            $data=[
                'code'=>$this->code,
                'life'=>$now+$this->max_life,
                'next_time'=>$now+$this->next_send_time
            ];

        }
        Cache::set($this->key,$data,$this->max_life);
    }

    /**
     * 验证码是否是有效期内
     * @return bool
     */
    function checkLife(){
        $now=time();
        if($this->life>0){
            return $now<$this->life;
        }
        return false;
    }


    /**
     * 是否可以再次发送
     */
    function checkSendTime(){
        $now=time();
        if($this->next_time>0){
            return $now>$this->next_time;
        }
        return true;
    }

    //检测验证码是否正确
    function checkCode($code){
        $debug=config('sms.debug');
        if($debug && $code==self::DEFAULT_CODE){
            return true;
        }
        if($this->checkLife() && $this->code && $this->code==$code){
            //验证码正确
            $this->save(true);
            return true;

        }

        return false;
    }

    function sendSms(){
        if(!checkMobile($this->name)){
            throw new BaseException('手机号码不正确');
        }

        $config = [
            'accessKeyId'    => config('sms.accessKeyId'),
            'accessKeySecret' => config('sms.accessKeySecret'),
        ];

        if(!$this->checkSendTime()){
            throw new BaseException('发送短信太频繁，请稍候再发');
        }

        $this->code=random_code();
        $signame=config('sms.signName');
        $template_arr=config('sms.template');
        $client  = new Client($config);
        $sendSms = new SendSms;
        $sendSms->setPhoneNumbers($this->name);
        $sendSms->setSignName($signame);
        $sendSms->setTemplateCode($template_arr[$this->scene]);
        $sendSms->setTemplateParam(['code' => $this->code]);
        $sendSms->setOutId('notice');
        $result = $client->execute($sendSms);
        if (isset($result->Code) && $result->Code == "OK"){
            $this->save();
            return true;
        }else{
            \think\Log::write($result,'SMS_ERROR');
            throw new BaseException('发送失败，请稍候再试');
        }

        return false;

    }

    /**
     * 获取邮件的主题
     */
    function getMailSubject(){
        if(isset($this->mail_template[$this->scene])){
            return $this->mail_template[$this->scene]['subject'];
        }
        return '邮箱验证';
    }


    function getMailContent(){
        if(isset($this->mail_template[$this->scene])){
            return $this->mail_template[$this->scene]['content'];
        }

        return '<p>这封邮件没有内容，完全是测试的吗？验证码是s%</p>';
    }

    function sendMail($nickname=''){

        if(!filter_var($this->name,FILTER_VALIDATE_EMAIL)){
            throw new BaseException('邮箱格式不正确');
        }

        if(!$this->checkSendTime()){
            throw new BaseException('发送短信太频繁，请稍候再发');
        }

        $this->code=random_code();
        $config=config('email');
        //加载文件
        $phpmailer=new PHPMailer();
        // 设置PHPMailer使用SMTP服务器发送Email
        $phpmailer->IsSMTP();
        // 设置为html格式
        $phpmailer->IsHTML(true);
        // 设置邮件的字符编码'
        $phpmailer->CharSet='UTF-8';
        // 设置SMTP服务器。
        $phpmailer->Host=$config['host'];
        // 设置为"需要验证"
        $phpmailer->SMTPAuth=true;
        // 设置发件箱帐号
        $phpmailer->Username=$config['username'];
        // 设置授权密码
        $phpmailer->Password=$config['password'];
        // 设置邮件头的From字段。
        $phpmailer->From=$config['from'];
        // 设置发件人名字
        $phpmailer->FromName=$config['from_name'];
        // 添加收件人地址，可以多次使用来添加多个收件人
        $phpmailer->AddAddress($this->name,$nickname);

        // 设置邮件标题
        $phpmailer->Subject=$this->getMailSubject();
        // 设置邮件正文
        if($nickname){
            $body="<p>亲爱的{$nickname}：</p>";
        }
        $content=$this->getMailContent();
        $content=sprintf($content,$this->code);
        $body=$body.$content.'<hr>';
        $body.="<p>{$config['from_name']}</p>";
        $body.='<p>'.date('Y-m-d H:i:s').'</p>';
        $phpmailer->Body=$body;

        // 发送邮件。
        if(!$phpmailer->Send()) {
            throw new BaseException($phpmailer->ErrorInfo);
        }else{
            $this->save();
            return true;
        }

    }

}
